package com.example.nextstream.ws;

import com.example.nextstream.guacd.MyGuacamoleClientInformation;
import com.example.nextstream.service.ClientSessionService;
import com.example.nextstream.service.PropertiesService;
import com.example.nextstream.service.SessionStore;
import com.example.nextstream.utils.RequestUtil;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleSocket;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.InetGuacamoleSocket;
import org.apache.guacamole.net.SimpleGuacamoleTunnel;
import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/api/v1/ws/{sessionId}", subprotocols = "guacamole")
@Component
public class WebSocketTunnel extends GuacamoleWebSocketTunnelEndpoint {
    private final Logger logger = LoggerFactory.getLogger(GuacamoleWebSocketTunnelEndpoint.class);

    //注入bean
    private static ClientSessionService clientSessionService;


    @Autowired
    public void setPropertiesService(PropertiesService propertiesService) {
        this.propertiesService = propertiesService;
    }

    private static PropertiesService propertiesService;

    @Autowired
    public void setClientSessionService(ClientSessionService clientSessionService) {
        this.clientSessionService = clientSessionService;
    }

    private static String hostname;

    @Value("${guacamole.hostname}")
    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    private static Integer port;

    @Value("${guacamole.port}")
    public void setPort(int port) {
        this.port = port;
    }

    private static SessionStore sessionStore;

    public Boolean isLock = false;

    @Autowired
    public void setSessionStore(SessionStore sessionStore) {
        this.sessionStore = sessionStore;
    }

    @Override
    protected GuacamoleTunnel createTunnel(Session session, EndpointConfig endpointConfig) throws GuacamoleException {

        //get assets info
        String sessionId = session.getPathParameters().get("sessionId");
        String queryStrings = session.getQueryString();

        if (sessionStore.isSessionObj(sessionId)) {
            isLock = true;
            return null;
        }

        //set width and height
        String width = RequestUtil.getQueryStringE(queryStrings, "width");
        String height = RequestUtil.getQueryStringE(queryStrings, "height");
        String dpi = RequestUtil.getQueryStringE(queryStrings, "dpi");

        var assets = clientSessionService.getSessionByUUID(sessionId);

        GuacamoleConfiguration configuration = new GuacamoleConfiguration();
        //xieyi
        configuration.setProtocol(assets.getAssetsProtocol());
        configuration.setParameter("hostname", assets.getAssetsIp());
        configuration.setParameter("port", assets.getAssetsPort().toString());
        configuration.setParameter("username", assets.getAssetsUsername());
        configuration.setParameter("password", assets.getAssetsPassword());
        configuration.setParameter("width", width);
        configuration.setParameter("height", height);
        configuration.setParameter("dpi", dpi);
        if (assets.getAssetsProtocol().equals("rdp")) {
            configuration.setParameter("ignore-cert", "true");
            configuration.setParameter("security", "any");
            configuration.setParameter("resize-method", "reconnect");
            //configuration from database
            configuration.setParameter("enable-drive", propertiesService.getPropertiesById("enable-drive"));
            configuration.setParameter("drive-name", propertiesService.getPropertiesById("drive-name"));
            configuration.setParameter("disable-bitmap-caching", propertiesService.getPropertiesById("disable-bitmap-caching"));
            configuration.setParameter("disable-glyph-caching", propertiesService.getPropertiesById("disable-glyph-caching"));
            configuration.setParameter("disable-offscreen-caching", propertiesService.getPropertiesById("disable-offscreen-caching"));
            configuration.setParameter("drive-path", propertiesService.getPropertiesById("drive-path"));
            configuration.setParameter("enable-desktop-composition", propertiesService.getPropertiesById("enable-desktop-composition"));
            configuration.setParameter("enable-font-smoothing", propertiesService.getPropertiesById("enable-font-smoothing"));
            configuration.setParameter("enable-full-window-drag", propertiesService.getPropertiesById("enable-full-window-drag"));
            configuration.setParameter("enable-menu-animations", propertiesService.getPropertiesById("enable-menu-animations"));
            configuration.setParameter("enable-theming", propertiesService.getPropertiesById("enable-theming"));
            configuration.setParameter("enable-wallpaper", propertiesService.getPropertiesById("enable-wallpaper"));

            // configuration.setParameter();
        } else if (assets.getAssetsProtocol().equals("ssh")) {
            configuration.setParameter("font-size", propertiesService.getPropertiesById("font-size"));
            configuration.setParameter("font-name", propertiesService.getPropertiesById("font-name"));
            configuration.setParameter("color-scheme", propertiesService.getPropertiesById("color-scheme"));
            if (assets.getPrivateKey() != null && assets.getPrivateKey() != "" && assets.getPrivateKey() != "undefined") {
                configuration.setParameter("private-key", assets.getPrivateKey());
                configuration.setParameter("passphrase", assets.getPassphrase());
                configuration.unsetParameter("password");
            }
        }
        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket(hostname, port),
                configuration,
                new MyGuacamoleClientInformation()
        );
        GuacamoleTunnel tunnel = new SimpleGuacamoleTunnel(socket);

        sessionStore.setSessionObj(sessionId, tunnel);
        return tunnel;
    }

    @Override
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        super.onClose(session, closeReason);
        if (!isLock) {
            sessionStore.removeSessionObj(session.getPathParameters().get("sessionId"));
        }

    }

}
